// FeedTree.cpp : implementation file
//

#include "stdafx.h"
#include "tinypp.h"
#include "FeedTree.h"
#include "AboutDlg.h"
#include "FeedGroup.h"
#include "GroupSettingsDlg.h"
#include "AddFeedWizardDlg.h"
#include "DBManager.h"
#include "FeedFetcher.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// CFeedTree
#define IDM_ADD_NEW_GROUP 10001
#define IDM_ADD_NEW_FEED 10002
#define IDM_UPDATE_GROUP_OR_FEED 10003
#define IDM_DELETE_GROUP_OR_FEED 10004


CFeedTree::CFeedTree()
{
}

CFeedTree::~CFeedTree()
{
}

IMPLEMENT_DYNAMIC(CFeedTree, CTreeCtrl)

BEGIN_MESSAGE_MAP(CFeedTree, CTreeCtrl)
	//{{AFX_MSG_MAP(CFeedTree)
	ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteitem)
	//}}AFX_MSG_MAP
	ON_COMMAND(IDM_ADD_NEW_GROUP,OnAddNewGroup)
	ON_COMMAND(IDM_ADD_NEW_FEED,OnAddNewFeed)
	ON_COMMAND(IDM_UPDATE_GROUP_OR_FEED,OnUpdateGroupOrFeed)
	ON_COMMAND(IDM_DELETE_GROUP_OR_FEED,OnDeleteGroupOrFeed)
	ON_WM_RBUTTONDOWN()
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFeedTree message handlers
void CFeedTree::OnRButtonDown(UINT nFlags, CPoint point)
{
	CMenu context;
	context.CreatePopupMenu();
	ClientToScreen(&point);
	context.AppendMenu(MF_STRING|MF_ENABLED,IDM_ADD_NEW_GROUP,_T("Create New Group"));
	context.AppendMenu(MF_STRING|MF_ENABLED,IDM_ADD_NEW_FEED,_T("Create New Feed"));
	context.AppendMenu(MF_STRING|MF_ENABLED,IDM_UPDATE_GROUP_OR_FEED,_T("Update!"));
	context.AppendMenu(MF_STRING|MF_ENABLED,IDM_DELETE_GROUP_OR_FEED,_T("Delete"));
	context.TrackPopupMenu( TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RIGHTBUTTON, point.x, point.y, this);
	//CTreeCtrl::OnRButtonDown(nFlags, point);
}

void CFeedTree::OnAddNewGroup()
{
	CGroupSettingsDlg dlg(this);
	if(dlg.DoModal() != IDOK)
		return;			
	HTREEITEM hCurrent = GetSelectedItem();
	if ( !hCurrent)
		hCurrent = TVI_ROOT;	
	InsertAGroup(dlg.m_strGroupName,"",hCurrent);
}


void CFeedTree::OnAddNewFeed()
{
	CAddFeedWizardDlg dlg;
	if(dlg.DoModal() != IDOK){
		return;
	}
	HTREEITEM hCurrent = GetSelectedItem();
	if ( !hCurrent)
		hCurrent = TVI_ROOT;	
	InsertAFeed(dlg.m_strFeedUrl,dlg.m_strFeedTitle,hCurrent);	
}

void CFeedTree::OnUpdateGroupOrFeed()
{
	HTREEITEM hCurrent = GetSelectedItem();
	if(hCurrent == TVI_ROOT)
		return;
	RSSFeed* pFeed = GetRSSFeed(hCurrent);
	FeedGroup* pGroup = GetFeedGroup(hCurrent);
		
	if (pFeed) {
		FeedFetcher::Instance()->FetchAFeed(pFeed);
	}else if(pGroup){
		FeedFetcher::Instance()->FetchAGroup(pGroup);
	}else{
		return;
	}	
}


void CFeedTree::OnDeleteGroupOrFeed()
{
	HTREEITEM hCurrent = GetSelectedItem();
	if(hCurrent == TVI_ROOT)
		return;
	RSSFeed* pFeed = GetRSSFeed(hCurrent);
	FeedGroup* pGroup = GetFeedGroup(hCurrent);
	
	CString strConfirmMsg;
	if (pFeed) {
		strConfirmMsg.Format("are you sure you want to delete feed: [ %s ]",pFeed->GetTitle());
		if( MessageBox(strConfirmMsg,"Confirm",MB_YESNO) != IDYES)
			return;
		DBManager::Instance()->DeleteAFeed(pFeed);
		DeleteItem(hCurrent);
	}else if(pGroup){
		strConfirmMsg.Format("are you sure you want to delete the group:[ %s ]",pGroup->GetGroupName());
		if( MessageBox(strConfirmMsg,"Confirm",MB_YESNO) != IDYES)
			return;
		DBManager::Instance()->DeleteAGroup(pGroup);
		DeleteItem(hCurrent);
	}else{
		return;
	}	
}


HTREEITEM CFeedTree::InsertAGroup(const char* name, const char* description, HTREEITEM hParent /*=TVI_ROOT*/)
{	
	int nParentID=0; // no parent
	if (hParent != TVI_ROOT) {
		nParentID=GetFeedGroup(hParent)->m_nFeedGroupID;
	}
	
	FeedGroup* pGroup=new FeedGroup(name,description,nParentID);


	if(!DBManager::Instance()->InsertAGroup(pGroup))
		return false;	

	return InsertAGroupToTree(pGroup,hParent);
}

HTREEITEM CFeedTree::InsertAGroupToTree(FeedGroup* pGroup, HTREEITEM hParent /*=TVI_ROOT*/)
{	
	
	TV_INSERTSTRUCT tvis;
	tvis.hParent = hParent;
	tvis.hInsertAfter = TVI_LAST;
	tvis.item.mask =  TVIF_TEXT | TVIF_PARAM; 	
	tvis.item.lParam = reinterpret_cast<LPARAM>(new TREE_NODE_PARAM(pGroup));
	tvis.item.pszText=(char*)pGroup->m_strGroupName.c_str();

	HTREEITEM hCurrent=InsertItem(&tvis);
	//EnsureVisible( hCurrent);
	return hCurrent;
}

HTREEITEM CFeedTree::InsertAFeedToTree(RSSFeed* pFeed, HTREEITEM hParent /*=TVI_ROOT*/)
{
	TV_INSERTSTRUCT tvis;
	tvis.hParent = hParent;
	tvis.hInsertAfter = TVI_LAST;
	tvis.item.mask =  TVIF_TEXT | TVIF_PARAM; 	
	tvis.item.lParam = reinterpret_cast<LPARAM>(new TREE_NODE_PARAM(pFeed));
	tvis.item.pszText=(char*)pFeed->m_strChannelTitle.c_str();

	HTREEITEM hCurrent=InsertItem(&tvis);
	//EnsureVisible( hCurrent);
	return hCurrent;
}

bool CFeedTree::InsertAFeed(const char* link, const char* title, HTREEITEM hParent /*=TVI_ROOT*/)
{	
	int nGroupID=0; // no parent
	if (hParent != TVI_ROOT) {
		nGroupID=GetFeedGroup(hParent)->m_nFeedGroupID;
	}
	
	RSSFeed* pFeed = new RSSFeed(link, title, nGroupID);

	if(!DBManager::Instance()->InsertAFeed(pFeed))
		return false;

	InsertAFeedToTree(pFeed,hParent);
	return true;
}

// initialize the tree from database
void CFeedTree::InitTree()
{
	std::queue<HTREEITEM> queue_TreeNodes;
	std::queue<int> queue_GroupIds;

	queue_GroupIds.push(0);
	queue_TreeNodes.push(TVI_ROOT);

	while( !queue_GroupIds.empty() )
	{
		HTREEITEM treeParent = queue_TreeNodes.front();
		int nID = queue_GroupIds.front();
		
		queue_TreeNodes.pop();
		queue_GroupIds.pop();

		HTREEITEM thisnode = TVI_ROOT;
		if(nID != 0 ){
			//get the group from db and insert it into the tree
			FeedGroup* pGroup = DBManager::Instance()->CreateGroupFromID(nID);
			if(pGroup){
				thisnode = InsertAGroupToTree(pGroup, treeParent);
			}			
		}
		vector<int> Childrens;
		int i=0;		
		//get children group ids 
		DBManager::Instance()->GetChildrenGroups(nID,Childrens);
		for(i=0;i<Childrens.size();i++){
			queue_GroupIds.push(Childrens[i]);
			queue_TreeNodes.push(thisnode);
		}

		//insert the feeds from db
		DBManager::Instance()->GetChildrenFeeds(nID,Childrens);
		for(i=0;i<Childrens.size();i++){
			RSSFeed* pFeed = DBManager::Instance()->CreateFeedFromID(Childrens[i]);
			if(pFeed){
				InsertAFeedToTree(pFeed, thisnode);
			}			
		}
	}
}

void CFeedTree::OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult) 
{
	LPNMTREEVIEW pNMTreeView = reinterpret_cast<LPNMTREEVIEW>(pNMHDR);
	TVITEM* pItem = &pNMTreeView->itemOld;
	
	TREE_NODE_PARAM* lparam = reinterpret_cast<TREE_NODE_PARAM*>( GetItemData(pItem->hItem) );
	if(lparam)
		delete lparam;
	*pResult = 0;
}

